﻿using PageTypeBuilder.Abstractions;
using PageTypeBuilder.Discovery;

namespace PageTypeBuilderUI.Reflection
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using PageTypeBuilder;
    using PageTypeBuilder.Reflection;

    internal static class Extensions
    {
        // exists within ptb
        public static IEnumerable<PropertyInfo> GetPageTypePropertyGroupProperties(this Type pageTypeType)
        {
            return pageTypeType.GetPublicOrPrivateProperties().Where(propertyInfo => propertyInfo.HasAttribute(typeof(PageTypePropertyGroupAttribute)));
        }

        // exists within ptb
        public static bool HasAttribute(this MemberInfo memberInfo, Type attributeType)
        {
            return memberInfo.GetCustomAttributes(attributeType, false).Length > 0;
        }

        // exists within page type builder PageTypePropertyDefinitionLocator class
        public static IEnumerable<PageTypePropertyDefinition> GetPropertyGroupPropertyDefinitions(this IPageType pageType, PropertyInfo propertyGroupProperty)
        {
            PageTypePropertyGroupAttribute groupAttribute = GetPropertyAttribute<PageTypePropertyGroupAttribute>(propertyGroupProperty);
            PropertyInfo[] propertyGroupProperties = propertyGroupProperty.PropertyType.GetPublicOrPrivateProperties();

            foreach (PropertyInfo property in propertyGroupProperties)
            {
                PageTypePropertyAttribute attribute = GetPropertyAttribute<PageTypePropertyAttribute>(property);

                if (attribute == null)
                    continue;

                string resolvedPropertyName = ResolvePropertyName(propertyGroupProperty.Name, property.Name);
                attribute = AdjustPropertyGroupAttributeProperties(attribute, groupAttribute);

                yield return new PageTypePropertyDefinition(resolvedPropertyName, property.PropertyType, pageType, attribute);
            }
        }

        public static T GetPropertyAttribute<T>(this PropertyInfo propertyInfo)
        {
            return propertyInfo.GetCustomAttributes<T>().FirstOrDefault();
        }

        private static string ResolvePropertyName(string currentHierarchy, string propertyName)
        {
            return !string.IsNullOrEmpty(currentHierarchy)
                    ? string.Concat(currentHierarchy, "-", propertyName)
                    : propertyName;
        }

        // exists within page type builder PageTypePropertyDefinitionLocator class
        private static PageTypePropertyAttribute AdjustPropertyGroupAttributeProperties(PageTypePropertyAttribute attribute, PageTypePropertyGroupAttribute groupAttribute)
        {
            if (groupAttribute != null)
            {
                if (!string.IsNullOrEmpty(groupAttribute.EditCaptionPrefix))
                    attribute.EditCaption = groupAttribute.EditCaptionPrefix + attribute.EditCaption;

                if (groupAttribute.StartSortOrderFrom > 0)
                    attribute.SortOrder = groupAttribute.StartSortOrderFrom + attribute.SortOrder;
            }
            return attribute;
        }
    }
}
